package com.my.lucky.controller;

import com.my.lucky.config.IwencaiConfig;
import com.my.lucky.dto.StockFlowDTO;
import com.my.lucky.entity.StockLimitDown;
import com.my.lucky.entity.StockLimitUp;
import com.my.lucky.entity.StockQueryRecord;
import com.my.lucky.model.ReviewInfo;
import com.my.lucky.model.Stock;
import com.my.lucky.model.dto.StockSummaryDTO;
import com.my.lucky.repository.ReviewInfoRepository;
import com.my.lucky.repository.StockLimitDownRepository;
import com.my.lucky.repository.StockQueryRecordRepository;
import com.my.lucky.repository.StockRepository;
import com.my.lucky.service.GaiNianInfoService;
import com.my.lucky.service.StockDataLoader;
import com.my.lucky.service.StockLimitUpService;
import com.my.lucky.service.StockService;
import com.my.lucky.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/stocksflow")
public class StockFlowController {

    private final StockService stockService;
    @Autowired
    StockDataLoader loader;
    @Autowired
    private StockRepository stockRepository;
    @Autowired
    private StockLimitUpService stockLimitUpService;

    @Autowired
    private ReviewInfoRepository reviewInfoRepository;

    @Autowired
    private StockLimitDownRepository downRepository;

    @Autowired
    private StockQueryRecordRepository stockQueryRecordRepository;

    @Autowired
    private GaiNianInfoService service;

    @Autowired
    private IwencaiConfig iwencaiConfig;

    @Autowired
    public StockFlowController(StockService stockService) {
        this.stockService = stockService;
    }

    /**
     * 计算两个用分隔符分割的字符串的差值
     *
     * @param focus       焦点字符串
     * @param allOptional 所有可选元素字符串
     * @param separator   分隔符
     * @return 存在于focus但不存在于allOptional的元素，用相同分隔符连接
     */
    private static String calculateDiff(String focus, String allOptional, String separator) {
        // 处理空字符串情况
        if (focus == null || focus.isEmpty()) {
            return "";
        }

        // 拆分字符串为集合
        String[] focusArray = focus.split(separator);
        String[] optionalArray = allOptional != null ? allOptional.split(separator) : new String[0];

        // 将所有可选元素放入HashSet，提高查找效率
        Set<String> optionalSet = new HashSet<>();
        for (String item : optionalArray) {
            optionalSet.add(item);
        }

        // 筛选出焦点中独有的元素
        List<String> diffList = new ArrayList<>();
        for (String item : focusArray) {
            if (!optionalSet.contains(item)) {
                diffList.add(item);
            }
        }
        // 将结果列表拼接回字符串
        return String.join(separator, diffList);
    }

    /**
     * 概念复盘
     */
    @GetMapping
    public String gainianPage(Model model) {
        LocalDate today = LocalDate.now();
        LocalDate yesterday = LocalDate.now().minusDays(1);//默认取2天数据
        if (today.getDayOfWeek() == DayOfWeek.MONDAY) {//周一取到周五的数据
            yesterday = today.with(DayOfWeek.FRIDAY).minusWeeks(1);
        } else if (today.getDayOfWeek() == DayOfWeek.SATURDAY || today.getDayOfWeek() == DayOfWeek.SUNDAY) {
            yesterday = today.with(DayOfWeek.THURSDAY);//周末取到周四周五的数据
        }
        LocalDate endDate = today;
        model.addAttribute("startDate", yesterday);
        model.addAttribute("endDate", endDate);
        return "stockflow";
    }

    @GetMapping("/summary")
    @ResponseBody
    public ResponseEntity<StockFlowDTO> getStockSummary(@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate) {
        if (startDate == null) {
            startDate = LocalDate.now();
        }
        StockFlowDTO re = new StockFlowDTO();
        log.info("getStockSummary====");
        List<StockSummaryDTO> summaryData = stockService.getStockSummaryData(startDate);
        re.setResult(summaryData);
        re.setFlowStock(iwencaiConfig.getFocus());
        re.setAllOptional(iwencaiConfig.getAllOptional());
        re.setFlowGainian(iwencaiConfig.getFocusGaiNian());
        String onlyFlowStock = calculateDiff(
                iwencaiConfig.getFocus(),
                iwencaiConfig.getAllOptional(),
                "," // 分隔符
        );

        re.setOnlyFlowStock(onlyFlowStock);

        log.info("getStockSummary");

//        List<Stock> allStock = stockRepository.findByCreatedAtBetweenOrderByRankPositionAsc(LocalDateTime.of(startDate, LocalTime.MIDNIGHT), LocalDateTime.of(startDate, LocalTime.MAX));
        List<Stock> allStock = stockRepository.findByTradeDateBetweenOrderByCodeAscTradeDateAsc(startDate, startDate);
//        log.info("stocks10d:findByTradeDateBetweenOrderByCodeAscTradeDateAsc="+allStock+"=="+LocalDateTime.of(startDate, LocalTime.MAX));
        log.info("stocks10d:findByTradeDateBetweenOrderByCodeAscTradeDateAsc=" + allStock.size() + "==" + LocalDateTime.of(startDate, LocalTime.MAX) + "====");

        List<StockLimitUp> stocks10d = loader.stocks10d;//stockLimitUpService.getTodayLimitUpStocksBy(endDate10d,LocalDateTime.of(startDate, LocalTime.MAX));
        if (stocks10d == null || stocks10d.size() < 1 || !startDate.isEqual(LocalDate.now())) {
            LocalDateTime endDate10d = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(startDate, LocalTime.MIDNIGHT), 10);//.toLocalDate();//today.minusDays(1)
            stocks10d = stockLimitUpService.getTodayLimitUpStocksBy(endDate10d, LocalDateTime.of(startDate, LocalTime.MAX));
        }

        log.info("stocks10d:getTodayLimitUpStocksBy:" + stocks10d.size() + "==" + LocalDateTime.of(startDate, LocalTime.MAX) + "====");

        Map<String, String> limit10dMap = new HashMap<>();
        if (stocks10d != null) {
            for (int i = 0; i < stocks10d.size(); i++) {
                StockLimitUp limitUp = stocks10d.get(i);
                if (limitUp != null) {
                    limit10dMap.put(limitUp.getStockCode(), limitUp.getStockCode());
                }
            }
        }
//      System.out.println(allStock);
        Integer stocksUP = 0;//上涨的家数
        Integer stocksDown = 0;//下跌的家数
        Integer stocksLimit = 0;//涨停的家数
        Integer stockspin = 0;//平的家数
        String limit10dstr = "";
        String notlimit10dstr = "";
        BigDecimal todayAll = new BigDecimal(0.0);
        BigDecimal todayAllMain = new BigDecimal(0.0); //总主力
        for (Stock stock : allStock) {
            todayAll = todayAll.add(stock.getCapitalFlow() == null ? new BigDecimal(0.0) : stock.getCapitalFlow());
            todayAllMain = todayAllMain.add(stock.getMainCapitalFlow() == null ? new BigDecimal(0.0) : stock.getMainCapitalFlow());
            re.setCreatedAt(stock.getCreatedAt());
            if (stock.getChangePercent() != null && stock.getChangePercent() > 0) {
                stocksUP = stocksUP + 1;
            } else if (stock.getChangePercent() != null && stock.getChangePercent() < 0) {
                stocksDown = stocksDown + 1;
            } else {
                stockspin = stockspin + 1;
            }
            if (limit10dMap.containsKey(stock.getCode())) {
                limit10dstr += stock.getCode() + ",";
            } else {
                notlimit10dstr += stock.getCode() + ",";
            }
        }

        List<StockQueryRecord> records =null;
        if (startDate.isEqual(LocalDate.now())){
            records = iwencaiConfig.getNow10Drecords();
//            System.out.println("===loader.now10Drecords==="+records);
        }else{
            LocalDateTime startDates = DateUtils.minusDaysExcludeWeekendAndYesterday(LocalDateTime.of(startDate, LocalTime.MIDNIGHT), 10);
            records = stockQueryRecordRepository.findByQueryTimeBetweenOrderByQueryTimeAsc(startDates, LocalDateTime.of(startDate, LocalTime.MAX));
        }
        if (records != null) {
//            String stockCodes = records.stream()
//                    // 提取每个对象的stockCode
//                    .map(StockQueryRecord::getStockCode)
//                    // 过滤可能的null值（可选，根据实际情况）
//                    .filter(Objects::nonNull)
//                    // 用逗号连接所有股票代码
//                    .collect(Collectors.joining(","));

            String stockCodes = records.stream()
                    // 提取每个对象的stockCode
                    .map(StockQueryRecord::getStockCode)
                    // 过滤可能的null值
                    .filter(Objects::nonNull)
                    // 去除重复的股票代码
                    .distinct()
                    // 用逗号连接所有股票代码
                    .collect(Collectors.joining(","));

            re.setSearchtr(stockCodes);
        }

        List<StockLimitDown> downstocks = downRepository.findTodayLimitUpStocksAndRecordTimeBetween(LocalDateTime.of(startDate, LocalTime.MIDNIGHT), LocalDateTime.of(startDate, LocalTime.MAX));

        List<StockLimitUp> stocks = stockLimitUpService.getTodayLimitUpStocksBy(LocalDateTime.of(startDate, LocalTime.MIDNIGHT), LocalDateTime.of(startDate, LocalTime.MAX));
        if (stocks != null) {
            String stockCodes = stocks.stream()
                    // 过滤出连续涨停次数为"首板涨停"的记录
                    .filter(stock -> "首板涨停".equals(stock.getConsecutiveLimitUpCount()))
                    // 提取每个对象的stockCode
                    .map(StockLimitUp::getStockCode)
                    // 过滤可能的null值
                    .filter(Objects::nonNull)
                    // 用逗号连接所有股票代码
                    .collect(Collectors.joining(","));

            String contistockCodes = stocks.stream()
                    // 过滤出连续涨停次数为"首板涨停"的记录
                    .filter(stock -> !"首板涨停".equals(stock.getConsecutiveLimitUpCount()))
                    // 提取每个对象的stockCode
                    .map(StockLimitUp::getStockCode)
                    // 过滤可能的null值
                    .filter(Objects::nonNull)
                    // 用逗号连接所有股票代码
                    .collect(Collectors.joining(","));

            re.setTodaylimitstr(stockCodes);
            re.setTodaylimitcontinuousstr(contistockCodes);
            stocksLimit = stocks.size();
        } else {
            stocksLimit = 0;
        }


        LocalDate rstartDate = LocalDate.now().minusDays(20);
        List<ReviewInfo> reviewInfos = reviewInfoRepository.findByReviewTimeBetween(rstartDate, LocalDate.now());
        String reviews = "";
        if (reviewInfos != null && !reviewInfos.isEmpty()) { // 补充非空列表判断，避免无意义遍历
            // Stream 拼接：过滤 null 对象 + 处理 getReviewStock() 返回 null 的情况 + 拼接
            reviews = reviewInfos.stream()
                    // 过滤掉 null 的 ReviewInfo 对象（避免空指针）
                    .filter(Objects::nonNull)
                    // 获取 reviewStock，若为 null 则替换为空字符串（避免拼接出 "null"）
                    .map(reviewInfo -> Optional.ofNullable(reviewInfo.getReviewStock()).orElse(""))
                    // 拼接（分隔符可自定义，如 "," 则改为 .collect(Collectors.joining(","))）
                    .collect(Collectors.joining(","));
        }
        re.setReview15dstr(reviews);

        re.setStocksLimit(stocksLimit);
        re.setStocksLimitDown(downstocks==null?0:downstocks.size());
        re.setStocksUP(stocksUP);
        re.setStocksDown(stocksDown);
        re.setStocksPin(stockspin);
        re.setAllstocks(allStock.size());
        re.setLimit10dstr(limit10dstr);
        re.setNotlimit10dstr(notlimit10dstr);
        re.setTodayAll(todayAll);
        re.setTodayAllMain(todayAllMain);

//        System.out.println(re.getAllOptional());
//        System.out.println(re);
        return ResponseEntity.ok(re);
    }

    /**
     * 分析个股的资金情况，支持通过code参数过滤并跳转到详情页
     *
     * @param code 股票代码，可选参数
     * @return 股票详情页面
     */
    @GetMapping("/summarystock")
    public String getStock(Model model, @RequestParam(required = false) String code, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate) {
        try {
            // 处理日期参数，默认查询最近60天
            LocalDate endDate = startDate;//
            if (endDate == null) {
                endDate = LocalDate.now();
            }
            LocalDate start = endDate.minusDays(60);

            // 验证日期有效性
            if (start.isAfter(endDate)) {
                model.addAttribute("error", "开始日期不能晚于结束日期");
                return "getstock";
            }

            StockFlowDTO re = new StockFlowDTO();
            // 调用服务层方法，传入代码和日期范围
            List<StockSummaryDTO> summaryData = stockService.findByCodeAndDateRange(code, start, endDate);
            Stock stock = stockRepository.findLatestStockByCodeOrName(code);
            if (stock != null) {
                model.addAttribute("currentCode", "[" + stock.getCode() + "]" + stock.getName() + ":" + stock.getConcept());
            }

            // 如果re的createdAt必须是LocalDateTime类型
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            if (stock != null && stock.getCreatedAt() != null) {
                LocalDateTime formattedDateTime = LocalDateTime.parse(
                        stock.getCreatedAt().format(formatter),
                        formatter
                );
//                System.out.println("formattedDateTimeformattedDateTime="+formattedDateTime);
                re.setCreatedAt(formattedDateTime);
            }

            re.setResult(summaryData);
            re.setFlowStock(iwencaiConfig.getFocus());
//            re.setAllOptional(iwencaiConfig.getAllOptional());
            re.setFlowGainian(iwencaiConfig.getFocusGaiNian());

            // 计算差异股票
            String onlyFlowStock = calculateDiff(
                    iwencaiConfig.getFocus(),
                    iwencaiConfig.getAllOptional(),
                    ","
            );
            re.setOnlyFlowStock(onlyFlowStock);
            // 补充页面所需的统计数据
            re.setAllstocks(summaryData.size());

//            re.setStocksLimit(stocksLimit);
//            re.setStocksUP(stocksUP);
//            re.setStocksDown(stocksDown);
//            re.setStocksPin(stockspin);
//            re.setAllstocks(allStock.size());
//            re.setLimit10dstr(limit10dstr);
//            re.setNotlimit10dstr(notlimit10dstr);
//            re.setTodayAll(todayAll);
//            re.setTodayAllMain(todayAllMain);

            // 将所有需要展示的数据添加到模型
            model.addAttribute("stockFlow", re);  // 完整的数据流对象
            model.addAttribute("hasData", !summaryData.isEmpty());  // 是否有数据标记
        } catch (Exception e) {
            log.error("获取股票数据失败，code={}", code, e);
            model.addAttribute("error", "获取数据失败：" + e.getMessage());
        }

        return "getstock";  // 跳转到getstock.html视图
    }

}